package service

import (
	"context"
	"errors"
	"golang.org/x/crypto/bcrypt"
	"jk-time/webook/internal/domain"
	"jk-time/webook/internal/repository"
)

var (
	ErrDuplicateUser         = repository.ErrDuplicateUser
	ErrInvalidUserOrPassword = errors.New("用户不存在或者密码不对")
)

type UserService interface {
	Create(ctx context.Context, u domain.User) error
	FindOrCreate(ctx context.Context, phone string) (domain.User, error)
	FindOrCreateWechat(ctx context.Context, info domain.Oauth2Info) (domain.User, error)
	FindOrCreateGithub(ctx context.Context, info domain.Oauth2Info) (domain.User, error)
	SignUp(ctx context.Context, u domain.User) error
	Login(ctx context.Context, email, password string) (domain.User, error)
}
type userService struct {
	repo repository.UserRepository
}

func NewUserService(repo repository.UserRepository) UserService {
	return &userService{repo: repo}
}

func (svc *userService) Create(ctx context.Context, u domain.User) error {
	return svc.repo.Create(ctx, u)
}
func (svc *userService) FindOrCreate(ctx context.Context, phone string) (domain.User, error) {
	u, err := svc.repo.FindByPhone(ctx, phone)
	if err != repository.ErrUserNotFound {
		//绝大部分请求来到这里
		//优先考虑已注册服务
		return u, err
	}
	//慢路径
	//用户没找到
	err = svc.repo.Create(ctx, domain.User{
		Phone: phone,
	})
	// 有两种可能，一种是 err 恰好是唯一索引冲突（phone）
	// 一种是 err != nil，系统错误
	if err != nil && err != ErrDuplicateUser {
		return domain.User{}, err
	}
	return svc.repo.FindByPhone(ctx, phone)
}
func (svc *userService) FindOrCreateWechat(ctx context.Context, info domain.Oauth2Info) (domain.User, error) {
	u, err := svc.repo.FindByWechat(ctx, info.OpenId)
	if err != repository.ErrUserNotFound {
		//绝大部分请求来到这里
		//优先考虑已注册服务
		return u, err
	}
	//慢路径
	//用户没找到
	err = svc.repo.Create(ctx, domain.User{
		Wechat: info,
	})
	// 有两种可能，一种是 err 恰好是唯一索引冲突（phone）
	// 一种是 err != nil，系统错误
	if err != nil && err != ErrDuplicateUser {
		return domain.User{}, err
	}
	return svc.repo.FindByWechat(ctx, info.OpenId)
}
func (svc *userService) FindOrCreateGithub(ctx context.Context, info domain.Oauth2Info) (domain.User, error) {
	u, err := svc.repo.FindByGithub(ctx, info.GithubId)
	if err != repository.ErrUserNotFound {
		//绝大部分请求来到这里
		//优先考虑已注册服务
		return u, err
	}
	//慢路径
	//用户没找到
	err = svc.repo.Create(ctx, domain.User{
		Wechat: info,
	})
	// 有两种可能，一种是 err 恰好是唯一索引冲突（phone）
	// 一种是 err != nil，系统错误
	if err != nil && err != ErrDuplicateUser {
		return domain.User{}, err
	}
	return svc.repo.FindByGithub(ctx, info.GithubId)
}
func (svc *userService) SignUp(ctx context.Context, u domain.User) error {
	hash, err := bcrypt.GenerateFromPassword([]byte(u.Password), bcrypt.DefaultCost)
	if err != nil {
		return err
	}
	u.Password = string(hash)
	return svc.repo.Create(ctx, u)
}
func (svc *userService) Login(ctx context.Context, email, password string) (domain.User, error) {
	u, err := svc.repo.FindByEmail(ctx, email)
	if err == repository.ErrUserNotFound {
		return domain.User{}, ErrInvalidUserOrPassword
	}
	if err != nil {
		return domain.User{}, err
	}
	err = bcrypt.CompareHashAndPassword([]byte(u.Password), []byte(password))
	if err != nil {
		return domain.User{}, ErrInvalidUserOrPassword
	}
	return u, nil
}

//func (svc *UserService) FindById(ctx context.Context, uid int64)(domain.User, error){
//	svc.repo.
//}
